import os
from flask import (Blueprint,
                   request,
                   render_template,
                   jsonify,
                   current_app,
                   make_response,
                   session,
                   g,
                   redirect,
                   url_for)
from flask_mail import Message
from utils import resetful
import string, random, time
from exts import mail, cache,db
from flask_avatars import Identicon
from utils.captcha import Captcha
from hashlib import md5
from io import BytesIO
from .forms import RegisterForm,LoginForm,UploadAvatarForm, EditProfileForm,UploadImageForm, PublicPostForm, CommentForm
from models.auth import UserModel
from models.post import BoardModel,PostModel,CommentModel
from .decorators import login_required
from flask_paginate import get_page_parameter,Pagination
from sqlalchemy.sql import func
bp = Blueprint("front", __name__, url_prefix='/')

# 请求=>before_request=>返回模板=>context_processor=>将变量添加到模板上并返回

@bp.before_request
def front_before_request():
    if "user_id" in session:
        user_id=session.get('user_id')
        user=UserModel.query.get(user_id)
        setattr(g,"user",user)

@bp.context_processor
def front_context_professor():
    if hasattr(g,"user"):
        return {"user":g.user}
    else:
        return {}

@bp.route('/')
def index():
    bd=request.args.get("bd",type=int,default=None)
    st=request.args.get("st",type=int,default=1)
    boards=BoardModel.query.order_by(BoardModel.priority.desc()).all()
    posts_query=None
    if st==1:
        posts_query=PostModel.query.order_by(PostModel.create_time.desc())
    elif st==3:
        posts_query=db.session.query(PostModel).outerjoin(CommentModel).\
            group_by(PostModel.id).\
            order_by(func.count(CommentModel.id).desc(),PostModel.create_time.desc())
    if bd:
        posts_query=posts_query.filter(PostModel.board_id==bd)
    total_post_count=posts_query.count()
    page=request.args.get(get_page_parameter(),type=int,default=1)
    start=(page-1)*current_app.config['PER_PAGE_COUNT']
    end=start+current_app.config['PER_PAGE_COUNT']
    posts=posts_query.slice(start,end)
    pagination=Pagination(bs_version=3,page=page,total=total_post_count,prev_label="上一页",next_label="下一页")
    context={
        "boards":boards,
        "posts":posts,
        "pagination":pagination,
        "sort":st,
        "board_id":bd
    }
    return render_template('front/index.html',**context)


@bp.route('/login/', methods=['GET', 'POST'])
def login():
    if (request.method == 'GET'):
        return render_template("front/login.html")
    else:
        form=LoginForm(request.form)
        if form.validate():
            email=form.email.data
            password=form.password.data
            remember=form.remember.data
            user=UserModel.query.filter_by(email=email).first()
            if user and user.check_password(password):
                session['user_id']=user.id
                if remember:
                    session.permanent=True
                return resetful.ok()
            else:
                return resetful.params_error(message='邮箱或者密码错误!')
        else:
            message=form.messages[0]
            return resetful.params_error(message=message)

@bp.get('/logout/')
def logout():
    session.clear()
    return redirect(url_for("front.index"))

@bp.route('/register/', methods=['GET', 'POST'])
def register():
    if (request.method == 'GET'):
        return render_template("front/register.html")
    else:
        form=RegisterForm(request.form)
        if form.validate():
            email=form.email.data
            username=form.username.data
            password=form.password1.data
            # 根据邮箱随机生成头像
            identicon=Identicon()
            filename=identicon.generate(text=md5(email.encode('utf8')).hexdigest())
            avatar=filename[2]
            user=UserModel(email=email,username=username,password=password,avatar=avatar)
            db.session.add(user)
            db.session.commit()
            return resetful.ok()
        else:
            message=form.messages[0]
            return resetful.params_error(message=message)


# 发送邮件
@bp.get('/email/captcha/')
def get_email_captcha():
    email = request.args.get('email')
    if not email:
        return resetful.params_error(message="请传递邮箱")
    source = list(string.digits)
    mail_code = "".join(random.sample(source, 6))
    subject = '【邮箱验证码】'
    body = "邮箱验证码为%s" % mail_code
    current_app.celery.send_task("send_mail", (email, subject, body))
    cache.set(email, mail_code)
    print(cache.get(email))
    return resetful.ok(message="邮件发送成功!")


# 图形验证码
@bp.get('/image/captcha/')
def get_img_captcha():
    # 生成图形验证码
    text, image = Captcha.gene_graph_captcha()
    print(text)
    # 对验证码进行加密
    key = md5((text + str(time.time())).encode('utf8')).hexdigest()
    # 存入redis中
    cache.set(key, text)
    # 图片转化为二进制存进response中，验证字段存入cookie中
    out = BytesIO()
    image.save(out, "png")
    out.seek(0)
    resp = make_response(out.read())
    resp.set_cookie('_image_captcha', key, max_age=3600)
    resp.content_type = 'image/png'
    return resp

# 个人设置
@bp.get('/setting/')
@login_required
def front_setting():
    return render_template("front/setting.html")

@bp.post('/upload/avatar/')
@login_required
def upolad_avatar():
    form=UploadAvatarForm(request.files)
    if form.validate():
        avatar=form.avatar.data
        filename=avatar.filename
        _,suffix=os.path.splitext(filename)
        filename=md5((g.user.email+str(time.time())).encode('utf8')).hexdigest()+suffix
        avatar_path=os.path.join(current_app.config['AVATARS_SAVE_PATH'],filename)
        avatar.save(avatar_path)
        g.user.avatar=filename
        db.session.commit()
        return resetful.ok(data={'avatar':filename})
    else:
        message=form.messages[0]
        return resetful.params_error(message=message)

@bp.post('/setting/profile/')
@login_required
def edit_profile():
    form=EditProfileForm(request.form)
    if form.validate():
        signature=form.signature.data
        g.user.signature=signature
        db.session.commit()
        return resetful.ok()
    else:
        message=form.messages[0]
        return resetful.params_error(message=message)

@bp.route('/public/post/',methods=['GET','POST'])
@login_required
def public_post():
    if request.method=='GET':
        boards = BoardModel.query.order_by(BoardModel.priority.desc()).all()
        return render_template('front/public_post.html',boards=boards)
    else:
        form=PublicPostForm(request.form)
        if form.validate():
            title=form.title.data
            content=form.content.data
            board_id=form.board_id.data
            try:
                board=BoardModel.query.get(board_id)
            except Exception as e:
                print(e)
                return resetful.params_error(message='版块不存在!')
            post=PostModel(title=title,content=content,board=board,author=g.user)
            db.session.add(post)
            db.session.commit()
            return resetful.ok(data={'post_id':post.id})
        else:
            message=form.messages[0]
            return resetful.params_error(message=message)

@bp.get("/post/detail/<post_id>")
def get_post_detail(post_id):
    try:
        post=PostModel.query.get(post_id)
    except Exception as e:
        print(e)
        return "404"
    comment_num=CommentModel.query.filter_by(post_id=post_id).count()
    context={
        'CommentNum':comment_num,
        'post':post
    }
    return render_template('front/post_detail.html',**context)

@bp.post('/upload/post/image/')
@login_required
def upolad_post_image():
    form=UploadImageForm(request.files)
    if form.validate():
        image=form.image.data
        print(image)
        filename=image.filename
        _,suffix=os.path.splitext(filename)
        filename=md5((g.user.email+str(time.time())).encode('utf8')).hexdigest()+suffix
        image_path=os.path.join(current_app.config['POSTIMG_SAVE_PATH'],filename)
        image.save(image_path)
        return jsonify({"errno": 0, "data": [{
            "url": url_for("media.get_post_image", filename=filename),
            "alt": filename,
            "href": ""
        }]})
    else:
        return jsonify({
            "errno": 1,
            "message": "上传失败!"
        })

@bp.post('/post/comment/')
@login_required
def comment_post():
    form=CommentForm(request.form)
    if form.validate():
        post_id=form.post_id.data
        content=form.content.data
        try:
            post=PostModel.query.get(post_id)
        except Exception as e:
            print(e)
            return  resetful.params_error(message="帖子不存在")
        comment=CommentModel(content=content,post=post,author=g.user)
        db.session.add(comment)
        db.session.commit()
        return resetful.ok()
    else:
        message=form.messages[0]
        return resetful.params_error(message=message)
